package motivationalShoes;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Scanner;

import communications.BluetoothHandler;
import communications.EmailHandler;

import database.DatabaseHandler;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * The Main class is the system in its current shape. It contains the main loop
 * and allows for custom, manual manipulation of the database and some settings
 * before starting up the system.
 *
 * @author Robin Persson
 */

public class Main {
	
	private static final int performanceThreshold = 120; //in percent
	
	private static DatabaseHandler databaseHandler = DatabaseHandler.getInstance();
	private static BluetoothHandler bluetoothHandler;
	private static EmailHandler emailHandler;
	
	private static Logger logger = Logger.getLogger("motivationalShoes.Main");
	
	/**
	 * Generates data for one run session, 10 days +- 2 days ago.
	 * Session lasts for 30 minutes +- 10 minutes.
	 * Step intervals are around 0.4 seconds +- 0.05
	 */
	public static ArrayList<Long> generateData(String daysAgoString) {
		int daysAgo = 10;
		ArrayList<Long> timestampList = new ArrayList<Long>();
		try {
			daysAgo = Integer.parseInt(daysAgoString);
		} catch(NumberFormatException ex) {}
		
		long temp;
		
		long millis = 1;
		long seconds = 1000 * millis;
		long minutes = 60 * seconds;
		long hours = 60 * minutes;
		long days = 24 * hours;
		
		temp = Math.round(2 * days * Math.random()) - days;
		long timeAgo = (daysAgo * days) + temp;
		
		temp = Math.round(10 * minutes * Math.random()) - (5 * minutes);
		long duration = (30 * minutes) + temp;
		
		temp = Math.round(50 * millis * Math.random()) - (25 * millis);
		long stepInterval = (400 * millis) + temp;
		
		long timestamp = (new Date().getTime()) - timeAgo;
		long stepTimestamp = timestamp;
		long endTimestamp = timestamp + duration;
		while(stepTimestamp < endTimestamp) {
			timestampList.add(stepTimestamp);
			stepTimestamp += stepInterval;
		}
		
		return timestampList;
	}
	
	public static void main(String[] args) {
		boolean initializing = true;
		

		long millis = 1;
		long seconds = 1000 * millis;
		long minutes = 60 * seconds;
		long hours = 60 * minutes;
		long days = 24 * hours;
		
		//init
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String in = "";
		
		while(initializing) {
			System.out.println("Functions:");
			System.out.println("resetdb - clear the database and start from scratch.");
			System.out.println("viewdb - view all the contents of the db.");
			System.out.println("filldb [days] - fill the database with " +
								"one session \"days\" (10 if unspecified) days ago.");
			System.out.println("setemail [address] - Set the e-mail address to [address].");
			System.out.println("getemail - View the currently set e-mail address.");
			System.out.println("sendbademail - Send an e-mail, using the been-a-while texts as body.");
			System.out.println("sendgoodemail - Send an e-mail, using the good-performance texts as body.");
			System.out.println("start - Start the system.");
			
			System.out.print("\nChoose function: ");
			try {
				in = br.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if(in.equals("resetdb")) {
				databaseHandler.clearTables();
				databaseHandler.createTables();
				System.out.println("Database reset.");
			} else if(in.equals("viewdb")) {
				System.out.println(databaseHandler.getData());
			} else if(in.startsWith("filldb")) {
				String daysAgoString = "";
				Scanner sc = new Scanner(in);
				sc.next();
				if(sc.hasNext()) {
					daysAgoString = sc.next();
				}
				databaseHandler.newRunSession(generateData(daysAgoString));
				System.out.println("Added new session from generated data.");
			} else if(in.equals("start")) {
				System.out.println("System \"running\"");
				initializing = false;
			} else if(in.startsWith("setemail")) { 
				String address = "";
				Scanner sc = new Scanner(in);
				sc.next();
				if(sc.hasNext()) {
					address = sc.next();
				}
				if(EmailHandler.isValid(address)) {
					databaseHandler.setAddress(address);
					if(emailHandler == null) {
						emailHandler = new EmailHandler(address);
					} else {
						emailHandler.setAddress(address);
					}
				} else {
					System.out.println("Invalid e-mail address.\n_______________________\n");
				}
			} else if(in.equals("getemail")) {
				String address = databaseHandler.getAddress();
				startEmailHandler();
				emailHandler.setAddress(address);
				System.out.println("Current e-mail address: " + address);
			} else if(in.equals("sendbademail")) {
				if(emailHandler == null) {
					System.out.println("E-mail address not specified.\n_______________________\n");
				} else {
					emailHandler.sendBeenAWhileEmail();
				}
			} else if(in.equals("sendgoodemail")) {
				if(emailHandler == null) {
					System.out.println("E-mail address not specified.\n_______________________\n");
				} else {
					emailHandler.sendGoodPerformanceEmail();
				}
			} else {
				System.out.println("Invalid command.\n_______________________\n");
			}
		}

		//System starts running here
		/*
		System.out.println("Name of Shoe device virtual COM port: ");
		String portName = "";
		try {
			portName = br.readLine();
		} catch (IOException ex) {}
		*/
		
		startEmailHandler();
		 
		boolean connected = false;

		String bName1 = "/dev/tty.FireFly-1142-SPP";
		String bName2 = "/dev/cu.FireFly-1142-SPP";
		String[] bName = new String[] {bName1, bName2};
		int i = 0;
		String s = bName[i];
			
		while(!connected) {
			try {
				bluetoothHandler = new BluetoothHandler(s);
				logger.log(Level.INFO, "Connected to shoe device!");
				connected = true;
			} catch(PortInUseException e) {
				logger.log(Level.SEVERE, null, e);
				System.exit(0);
			} catch(NoSuchPortException e) {
				long delay = 10; //in seconds
				logger.log(Level.INFO, "Shoe device not in range, new attempt in " +delay+ " seconds.");
				try {
					Thread.sleep(10*seconds);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
		}
		
		//INIT - SCHEDULE BEEN-A-WHILE TIMER
		TimerTask task = new SendBeenAWhileEmailTask(emailHandler, bluetoothHandler);
		Timer t = new Timer();
		long lastRunTimestamp;
		long beenAWhile;
		long interval = 5 * minutes;

			
		while(true) {
			lastRunTimestamp = databaseHandler.getLastRunTimestamp();
					
			bluetoothHandler.resetDevice();
					
			if(lastRunTimestamp > 5)
			{
				t = new Timer();
				task = new SendBeenAWhileEmailTask(emailHandler, bluetoothHandler);
				long now = new Date().getTime();
				beenAWhile = lastRunTimestamp;
				while(beenAWhile < now) {
					beenAWhile += interval;
				}
				t.schedule(task, new Date(beenAWhile), interval);
			}
			ArrayList<Long> data = new ArrayList<Long>();
			
			
			
			
			
			/*     For simulations: GENERATE DATA.
			System.out.print("Press any key to generate a new session...");
			String data;
			try {
				br.readLine(); //Simulate new data
				System.out.println("");
			} catch (IOException e) {
				e.printStackTrace();
			}
			data = generateData("0");
			
			*/
			
			boolean noData = true;
			while(noData) {
				try {
					data = bluetoothHandler.getNewData();
				} catch (IOException e) {}
				
				if(data.size() > 2)
				{
					//NEW DATA DISCOVERED
					noData = false;
					databaseHandler.newRunSession(data);
			
					if(databaseHandler.isGoodPerformance(performanceThreshold)) {
						emailHandler.sendGoodPerformanceEmail();
						bluetoothHandler.goodPerformance();
					}
					
					t.cancel();
				}
				else
				{
					try {
						int sleep = 15;
						logger.info("No new data, new attempt in " + sleep + " seconds.");
						Thread.sleep(sleep*1000);
					} catch (InterruptedException ex) {
						ex.printStackTrace();
					}
				}
			}
	
		}
	}
	
	private static void startEmailHandler() {
		if(emailHandler == null) {
			String address = databaseHandler.getAddress();
			emailHandler = new EmailHandler(address);
		}
	}

}
